<template>
    <div id="canvas-box">
        <div class="filter-box">
            <div class="filter-left">
                <span style="margin-left: 20px">人员列表：</span>
                <el-select v-model="checkedPonit" size="mini" clearable @change="handleChangePoint">
                    <el-option
                        v-for="item in pointOptions"
                        :key="item.id"
                        :value="item.name"
                        :label="item.name">
                    </el-option>
                </el-select>
            </div>
        </div>
        <div class="filter-box">
            <div class="filter-left">
                <i style='margin:0 10px'></i>
                <span>缩放：</span>
                <el-tooltip class="item" effect="dark" content="放大" placement="top">
                    <i class="el-icon-zoom-in" @click="onZoomIn"></i>
                </el-tooltip>
                <i style="margin:0 10px"></i>
                <el-tooltip class="item" effect="dark" content="缩小" placement="top">
                    <i class="el-icon-zoom-out" @click="onZoomOut"></i>
                </el-tooltip>
                <i style='margin:0 10px'></i>
                <span>移动：</span>
                <el-tooltip class="item" effect="dark" content="左移" placement="top">
                    <i class="el-icon-back" @click="onMove('left')"></i>
                </el-tooltip>
                <i style="margin:0 10px"></i>
                <el-tooltip class="item" effect="dark" content="上移" placement="top">
                    <i class="el-icon-top" @click="onMove('top')"></i>
                </el-tooltip>
                <i style="margin:0 10px"></i>
                <el-tooltip class="item" effect="dark" content="下移" placement="top">
                    <i class="el-icon-bottom" @click="onMove('bottom')"></i>
                </el-tooltip>
                <i style="margin:0 10px"></i>
                <el-tooltip class="item" effect="dark" content="右移" placement="top">
                    <i class="el-icon-right" @click="onMove('right')"></i>
                </el-tooltip>
            </div>
        </div>
        <div class='canvas-box'>
            <div class="canvas-wrapper"
                 :style="{ backgroundImage:`url(${url})`,backgroundSize: bgSize + '%' + ' ' + bgSize + '%',backgroundPosition: -bgPositionX + 'px' + ' ' + -bgPositionY + 'px'}">
                <div id="topology-canvas" style="width: 100%;height:100%;overflow:hidden;"></div>
            </div>
        </div>
        <div id="tip">
            <p>状态：{{ curData.online ? '在线' : '离线' }}</p>
            <p>姓名：{{ curData.name }}</p>
            <p>标签：{{ curData.tagName }}</p>
            <p>区域：{{ curData.regionName }}</p>
            <p>部门：{{ curData.deptName }}</p>
            <p>岗位：{{ curData.positionName }}</p>
        </div>
    </div>
</template>
<script>
// api
import { getAllPointsByTag } from '@/api/track'
import { Topology, Node, Point } from '@topology/core'
import { register as registerActivity } from '@topology/activity-diagram'
import { getNodes } from './tools'
import fenceRequest from '@/api/fence'
// 配置项
const canvasOptions = {
    font: {
        color: '#fff',
        fontSize: 12
    },
    // 连线颜色
    color: '#fff',
    keydown: -1,
    disableEmptyLine: true,
    disableScale: true,
    maxScale: 2,
    autoAnchor: false,
    autoExpandDistance: 0
}
const timex = 28.34 * (1 / (config.width * 28.34 / 1200))
const timey = 28.34 * (1 / (config.height * 28.34 / 600))

export default {
    data() {
        return {
            url: config.imageUrl,
            canvas: null,
            bgSize: 100,
            width: 1200,
            height: 600,
            bgPositionX: 0,
            bgPositionY: 0,
            direction: {
                x: 0,
                y: 0
            },
            curData: {},
            count: 0,
            pointOptions: [],
            checkedPonit: ''
        }
    },
    created() {
        registerActivity()
    },
    mounted() {
        this.initCanvas()
    },
    beforeDestroy() {
        this.canvas.destroy()
        this.canvas = null
    },
    methods: {
        initCanvas() {
            this.canvas = null
            canvasOptions.on = this.onMessage
            this.canvas = new Topology('topology-canvas', canvasOptions)
            this.canvas.data.locked = 2
            this.canvas.render()
            console.log(this.canvas)
            this.handleCode()
            this.handleNode()
        },
        // 选中点位
        handleChangePoint(val) {
            this.$startLoading()
            for (let i = 0; i < this.canvas.data.pens.length; i++) {
                let pen = this.canvas.data.pens[i]
                if (pen.data && pen.children && pen.children[0].visible) {
                    pen.children[0].visible = false
                    break
                }
            }
            for (let i = 0; i < this.canvas.data.pens.length; i++) {
                let pen = this.canvas.data.pens[i]
                console.log(pen)
                if (pen.data && (pen.data.name === val) && pen.children) {
                    pen.children[0].visible = true
                    break
                }
            }
            this.$endLoading()
        },
        /**
         *  设置栅栏
         * */
        handleCode() {
            fenceRequest.list().then(res => {
                if (res.status !== 200) return this.$msgPrompt.error(res.msg)
                let data = res.obj.filter(i => i.enable)
                data.forEach(item => {
                    let { x, y, width, height } = this.setCoordinate(JSON.parse(item.coordinate))
                    this.canvas.addNode(new Node({
                        text: item.name,
                        rect: {
                            width: width * timex,
                            height: height * timey,
                            x: Math.abs(x) * timex,
                            y: (config.height - y) * timey
                        },
                        borderRadius: 0,
                        bkType: 0,
                        fillStyle: item.colour,
                        globalAlpha: 0.6,
                        strokeStyle: 'transparent',
                        name: 'rectangle',
                        data: {
                            ...item, ...this.setCoordinate(JSON.parse(item.coordinate)),
                            type: 'code'
                        }
                    }))
                })
                this.canvas.render()
            })
        },
        // 设置坐标
        setCoordinate(data) {
            let { x, y } = data[1]
            let width = data[2].x - x
            let height = data[2].y - data[0].y
            return { x, y, width, height }
        },
        // 设置节点tips
        setNodeTips(node) {
            console.log(node)
            let parent = new Node(node)
            parent.tipId = 'tip'
            parent.hideInput = true
            parent.hideRotateCP = true
            parent.hideSizeCP = true
            parent.hideAnchor = true
            let child = new Node({
                text: '',
                rect: {
                    width: 24,
                    height: 20
                },
                name: 'image',
                image: '/mocks/image/tips.png'
            })
            // 设置子节点相对父节点属性
            child.rectInParent = {
                x: '50%',
                y: '0',
                width: '100%',
                height: '100%'
            }
            child.hideAnchor = true
            child.visible = false
            parent.setChild([child])
            return parent
        },
        /***
         *  设置实时点位
         */
        handleNode() {
            // 初始化调用一次
            this.task2()
            // 定时器调用
            const timer = setInterval(() => {
                this.task2()
            }, 2000)
            // 销毁定时器
            this.$once('hook:beforeDestroy', () => {
                clearInterval(timer)
            })
        },
        task2() {
            getAllPointsByTag().then(res => {
                if (res.status !== 200 || !res.obj) return
                let _data = res.obj
                this.pointOptions = res.obj
                // 计算新增节点 移除节点 存在节点
                let pens = this.canvas.data.pens.filter(pen => pen.data && pen.data.type !== 'code')
                let _addNodes = [], _removeNodes = [], _nodes = []
                _addNodes = _data.filter(el => pens.every(pen => pen.data.tagId !== el.tagId))
                _removeNodes = pens.filter(pen => _data.every(el => el.tagId !== pen.data.tagId))
                _nodes = _data.filter(el => pens.some(pen => pen.data.tagId === el.tagId))
                /**
                 *  新增节点
                 */
                // 传入列表返回为节点数据 遍历绘制节点
                getNodes(_addNodes).forEach((node) => {
                    this.canvas.addNode(this.setNodeTips(node), false)
                })

                /**
                 *  更新节点
                 */
                this.updateNodes([..._nodes, ..._addNodes])

                /**
                 *  移除节点
                 */
                _removeNodes.map(pen => pen.id).forEach(id => {
                    // 先接触锁定 删除之后 再锁定
                    this.canvas.data.locked = 0
                    this.canvas.delete(id)
                    this.canvas.data.locked = 2
                })
            })
        },
        // 更新节点位置
        updateNodes(points) {
            // 根据标签id 更新点位实时数据
            points.forEach(i => {
                this.canvas.data.pens.forEach(pen => {
                    if (pen.data && pen.data.type !== 'code' && pen.data.tagId === i.tagId) {
                        console.log(pen)
                        pen.data.online = i.online
                        // 根据比例设置x y 轴数据
                        pen.rect.x = i.x ? Math.round(Number(i.x) * timex) : pen.rect.x
                        pen.rect.y = i.y ? Math.round((config.height - Number(i.y)) * timey) : pen.rect.y
                        // 填充标签颜色
                        pen.fillStyle = i.colour
                        /**
                         *  由于节点scale方法是根据中心点进行等比缩放 包括节点宽高大小 x y 坐标
                         *  再者因为节点本身的位置重新赋值为1倍时，所以需要将节点宽高页初始化
                         *  保证调用缩放方法的一致性
                         * */
                        // 初始化节点宽高
                        pen.rect.width = pen.data.width
                        pen.rect.height = pen.data.height
                        pen.scale(this.bgSize / 100, new Point(this.width / 2, this.height / 2))
                    }
                })
                // 更新当前节点显示数据
                if (i.tagId === this.curData.tagId) {
                    this.curData.online = i.online
                }
            })
            this.canvas.updateProps('', this.canvas.data.pens)
        },
        onMessage(event, data) {
            if (event === 'moveInNode' && data.data && data.data.type !== 'code') {
                this.curData = data.data
            }
        },
        onZoomIn() {
            if (!this.canvas) return this.$msgPrompt.warning('人员轨迹不存在')
            this.canvas.translate(-((this.width * this.canvas.data.scale - this.width) / 2 - this.bgPositionX), -((this.height * this.canvas.data.scale - this.height) / 2 - this.bgPositionY))
            this.bgPositionX = (this.width * this.canvas.data.scale - this.width) / 2
            this.bgPositionY = (this.height * this.canvas.data.scale - this.height) / 2
            if (this.bgSize >= 200) {
                this.bgSize = 200
            } else {
                this.bgSize += 10
                let scale = Math.floor(this.canvas.data.scale * 100)
                scale += 10
                this.bgPositionX = (this.width * scale / 100 - this.width) / 2
                this.bgPositionY = (this.height * scale / 100 - this.height) / 2
                this.canvas.scaleTo(scale / 100, new Point(this.width / 2, this.height / 2))
            }
            console.log(this.canvas.data.pens)

        },
        onZoomOut() {
            if (!this.canvas) return this.$msgPrompt.warning('人员轨迹不存在')
            if (this.bgSize <= 100) {
                this.bgSize = 100
            } else {
                this.canvas.translate(-((this.width * this.canvas.data.scale - this.width) / 2 - this.bgPositionX), -((this.height * this.canvas.data.scale - this.height) / 2 - this.bgPositionY))
                this.bgPositionX = (this.width * this.canvas.data.scale - this.width) / 2
                this.bgPositionY = (this.height * this.canvas.data.scale - this.height) / 2
                this.bgSize -= 10
                let scale = Math.floor(this.canvas.data.scale * 100)
                scale -= 10
                this.bgPositionX = (this.width * scale / 100 - this.width) / 2
                this.bgPositionY = (this.height * scale / 100 - this.height) / 2
                this.canvas.scaleTo(scale / 100, new Point(this.width / 2, this.height / 2))
            }
            console.log(this.canvas.data.pens)

        },
        onMove(direction) {
            switch (direction) {
                case 'left':
                    console.log(this.bgPositionX)
                    if (this.bgPositionX <= 20) {
                        this.direction.x += this.bgPositionX
                        this.canvas.translate(this.bgPositionX, 0)
                        this.bgPositionX = 0
                    } else {
                        this.bgPositionX -= 20
                        this.direction.x += 20
                        this.canvas.translate(20, 0)
                    }
                    break
                case 'top':
                    if (this.bgPositionY <= 20) {
                        this.direction.y += this.bgPositionY
                        this.canvas.translate(0, this.bgPositionY)
                        this.bgPositionY = 0
                    } else {
                        this.bgPositionY -= 20
                        this.direction.y += 20
                        this.canvas.translate(0, 20)
                    }
                    break
                case 'right':
                    let lenR = this.width * this.canvas.data.scale - this.width - this.bgPositionX
                    if (lenR <= 20) {
                        this.direction.x -= lenR
                        this.canvas.translate(-lenR, 0)
                        this.bgPositionX = this.width * this.canvas.data.scale - this.width
                    } else {
                        this.bgPositionX += 20
                        this.direction.x -= 20
                        this.canvas.translate(-20, 0)
                    }
                    break
                case 'bottom':
                    let len = this.height * this.canvas.data.scale - this.height - this.bgPositionY
                    console.log(len)
                    if (len <= 20) {
                        this.direction.y -= len
                        this.canvas.translate(0, -len)
                        this.bgPositionY = this.height * this.canvas.data.scale - this.height
                    } else {
                        this.bgPositionY += 20
                        this.direction.y -= 20
                        this.canvas.translate(0, -20)
                    }
                    break
            }
        }
    }
}
</script>
<style lang='scss' scoped>
#canvas-box {
    background-color: #fff;
    margin: 0 10px;
    padding: 10px;
    min-width: 1250px;
    min-height: 650px;
    overflow: auto;
    display: flex;
    flex-direction: column;
}

.canvas-box {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    overflow: hidden;
}

.canvas-wrapper {
    width: 1200px;
    height: 600px;
    background-repeat: no-repeat;
}

.filter-left {
    i {
        font-size: 18px;
    }
}

// 提示
#tip {
    position: fixed;
    left: -99999px;
    background-color: rgba(0, 0, 0, .5);
    color: #ffffff;
    font-size: 14px;
    padding: 8px;
    line-height: 20px;
    border-radius: 5px;
    box-shadow: 0px 2px 2px rgba(0, 0, 0, .8);
}
</style>
